using System.IO;
using System.Text;
using CodePlex.UnitTestUtility;
using Xunit;

namespace CodePlex.TfsLibrary.ObjectModel
{
    public class WebTransferFormDataTest
    {
        [Fact]
        public void DoubleField()
        {
            TestableWebTransferFormData formData = TestableWebTransferFormData.Create();
            string result;
            string expected = string.Format(@"--{0}
Content-Disposition: form-data; name=""foo""

bar
--{0}
Content-Disposition: form-data; name=""baz""

biff
was
here
--{0}--
", formData.Boundary);

            formData.Add("foo", "bar");
            formData.Add("baz", "biff\r\nwas\r\nhere");

            using (MemoryStream stream = new MemoryStream())
            {
                formData.Render(stream);

                stream.Seek(0, SeekOrigin.Begin);
                byte[] bytes = new byte[stream.Length];
                stream.Read(bytes, 0, bytes.Length);
                result = Encoding.ASCII.GetString(bytes);
            }

            Assert.Equal(expected, result);
        }

        [Fact]
        public void OneFieldWithFile()
        {
            TestableWebTransferFormData formData = TestableWebTransferFormData.Create();
            formData.FileSystem.WriteAllText(@"C:\TempFile.txt", "biff\r\nwas\r\nover there...");
            string result;
            string expected = string.Format(@"--{0}
Content-Disposition: form-data; name=""foo""

bar
--{0}
Content-Disposition: form-data; name=""content""; filename=""baz""
Content-Type: application/octet-stream

biff
was
over there...
--{0}--
", formData.Boundary);

            formData.Add("foo", "bar");
            formData.AddFile("baz", @"C:\TempFile.txt");

            using (MemoryStream outputStream = new MemoryStream())
            {
                formData.Render(outputStream);

                outputStream.Seek(0, SeekOrigin.Begin);
                byte[] bytes = new byte[outputStream.Length];
                outputStream.Read(bytes, 0, bytes.Length);
                result = Encoding.ASCII.GetString(bytes);
            }

            Assert.Equal(expected, result);
        }

        [Fact]
        public void OneFieldWithFileBytes()
        {
            byte[] inputBytes = Encoding.ASCII.GetBytes("biff\r\nwas\r\nover there...");
            TestableWebTransferFormData formData = TestableWebTransferFormData.Create();
            string result;
            string expected = string.Format(@"--{0}
Content-Disposition: form-data; name=""foo""

bar
--{0}
Content-Disposition: form-data; name=""content""; filename=""baz""
Content-Type: application/octet-stream

biff
was
over there...
--{0}--
", formData.Boundary);

            formData.Add("foo", "bar");
            formData.AddFile("baz", inputBytes);

            using (MemoryStream outputStream = new MemoryStream())
            {
                formData.Render(outputStream);

                outputStream.Seek(0, SeekOrigin.Begin);
                byte[] bytes = new byte[outputStream.Length];
                outputStream.Read(bytes, 0, bytes.Length);
                result = Encoding.ASCII.GetString(bytes);
            }

            Assert.Equal(expected, result);
        }

        [Fact]
        public void SingleField()
        {
            TestableWebTransferFormData formData = TestableWebTransferFormData.Create();
            string result;
            string expected = string.Format(@"--{0}
Content-Disposition: form-data; name=""foo""

bar
--{0}--
", formData.Boundary);

            formData.Add("foo", "bar");

            using (MemoryStream stream = new MemoryStream())
            {
                formData.Render(stream);

                stream.Seek(0, SeekOrigin.Begin);
                byte[] bytes = new byte[stream.Length];
                stream.Read(bytes, 0, bytes.Length);
                result = Encoding.ASCII.GetString(bytes);
            }

            Assert.Equal(expected, result);
        }

        class TestableWebTransferFormData : WebTransferFormData
        {
            public readonly MockFileSystem FileSystem;

            TestableWebTransferFormData(MockFileSystem fileSystem)
                : base(fileSystem)
            {
                FileSystem = fileSystem;
            }

            public static TestableWebTransferFormData Create()
            {
                return new TestableWebTransferFormData(new MockFileSystem());
            }
        }
    }
}